package com.yzion.widgetlib.refreshrecyclerview;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.chad.library.adapter.base.BaseQuickAdapter;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 基本封装了 SmartRefreshLayout，RecycleView，BaseQuickAdapter
 * 让创建列表更加快速简单，对外接口尽量简单，如果需要，也可以调用 SmartRefreshLayout，或者 RecycleView，或者
 * BaseQuickAdapter里面的API，自由发挥
 * ZJJ
 */
public class RefreshRecyclerView extends FrameLayout implements View.OnClickListener {

    protected static final int CLICK_INTERVAL = 500;
    private long firClickTime = 0;
    private Map<Integer, Long> clickTimeMap;

    /**
     * 由三巨头配合完成
     */
    private SmartRefreshLayoutCompat mSmartRefreshLayout;
    private RecyclerView mRecyclerView;
    private BaseQuickAdapter mAdapter;

    /**
     * 状态View
     **/
    private View mEmptyView;
    private View mErrorView;

    /**
     * 记录一下 Adapter的 Header和 Footer
     **/
    private List<View> mAdapterHeaderList;
    private List<View> mAdapterFooterList;

    /**
     * 记录 itemType 类型所在列表位置 position
     **/
    private LinkedHashMap<Integer, Integer> typePositionMap;


    /**
     * 请求动作
     */
    private IRequestAction iRequestAction;

    /**
     * 点击事件
     */
    private OnItemClickListener OnItemClickListener;
    private OnStateViewClickListener OnStateClickListener;

    public RefreshRecyclerView(Context context) {
        this(context, null);
    }

    public RefreshRecyclerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RefreshRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initProperty(context, attrs);
    }

    private void initProperty(Context context, AttributeSet attrs) {
        typePositionMap = new LinkedHashMap<>();
        mAdapterHeaderList = new ArrayList<>();
        mAdapterFooterList = new ArrayList<>();
        clickTimeMap = new HashMap<>();
        initViews(context, attrs);
    }

    private void initViews(Context context, @Nullable AttributeSet attrs) {
        setClipToPadding(false);
        mSmartRefreshLayout = new SmartRefreshLayoutCompat(context);
        mSmartRefreshLayout.setEnableNestedScroll(true);
        mSmartRefreshLayout.setEnableAutoLoadMore(false);
        mSmartRefreshLayout.setEnableOverScrollBounce(false);
        mSmartRefreshLayout.setEnableFooterFollowWhenNoMoreData(true);
        mSmartRefreshLayout.setEnableLoadMoreWhenContentNotFull(false);
        mSmartRefreshLayout.setDisableContentWhenRefresh(false);
        mSmartRefreshLayout.setDisableContentWhenLoading(false);

        mSmartRefreshLayout.setClipToPadding(false);

        //设置默认的头部和尾部
//        mSmartRefreshLayout.setRefreshHeader(DefaultRefreshHeader.newInstance(getContext()));
//        mSmartRefreshLayout.setRefreshFooter(DefaultRefreshFooter.newInstance(getContext()));

        mRecyclerView = new RecyclerView(context);
        mRecyclerView.setVerticalScrollBarEnabled(true);
        mRecyclerView.setOverScrollMode(OVER_SCROLL_NEVER);
        mRecyclerView.setClipToPadding(false);
        mRecyclerView.setLayoutManager(new SmoothScrollLinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
        mSmartRefreshLayout.addView(mRecyclerView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

        addView(mSmartRefreshLayout);

    }

    private void initEvent() {

        mSmartRefreshLayout.setOnRefreshListener(refreshLayout -> {
//            LogUtils.d("onRefresh");
            if (iRequestAction != null) {
                iRequestAction.requestNewData();
            }
        });

        mSmartRefreshLayout.setOnLoadMoreListener(refreshLayout -> {
//            LogUtils.d("onLoadMore");
            if (iRequestAction != null) {
                iRequestAction.requestMoreData();
            }
        });

    }

    /**
     * 设置 RecyclerView 的列表布局类型
     * LinearLayoutManager 列表
     * GridLayoutManager 格子
     *
     * @param layoutManager
     */
    public void setLayoutManager(RecyclerView.LayoutManager layoutManager) {
        mRecyclerView.setLayoutManager(layoutManager);
    }

    @Override
    public void onClick(View view) {
        if (view == mEmptyView) {
            if (OnStateClickListener != null) {
                OnStateClickListener.onEmptyViewClick(view);
            }
        } else if (view == mErrorView) {
            if (OnStateClickListener != null) {
                OnStateClickListener.onErrorViewClick(view);
            }
        }
    }

    /**
     * 请求数据动作有2种
     * 1.下拉刷新，请求新数据 -> 请求完成后的数据手动调用 setNewData() 设置新数据
     * 2.加载更多，请求更多数据 -> 加载更多数据后手动调用 addMoreData() 将数据添加到列表尾部
     * <p>
     * 可以分别设置 SmartRefreshLayout.setOnRefreshListener()
     * 和 SmartRefreshLayout.setOnLoadMoreListener 来实现来下刷新的回调和加载更多的回调
     * <p>
     * 如果使用了 SmartRefreshLayout.setOnRefreshListener() 或者 SmartRefreshLayout.setOnLoadMoreListener
     * 此回调不会生效
     *
     * @param requestAction
     */
    public void setRequestAction(IRequestAction requestAction) {
        iRequestAction = requestAction;
        initEvent();
    }

    /**
     * 主动刷新数据，请看 setRequestAction
     */
    public void refreshData() {
        hideEmptyView();
        hideErrorView();

        if (mSmartRefreshLayout.autoRefresh()) {
//            LogUtils.d("autoRefresh ok");
        } else {
//            LogUtils.d("autoRefresh fail");
            if (iRequestAction != null) {
                iRequestAction.requestNewData();
            }
        }
    }

    /**
     * 主动加载更多，请看 setRequestAction，一般情况下不用自己主动调用，
     * 除非想主动控制加载更多的触发时机
     * 所以一般情况下，上拉加载更多的事件触发由 SmartRefreshLayout 控制
     * 当加载更多事件被触发后，会回调 IRequestAction.requestMoreData() 方法
     * 只需要在 requestMoreData 中实现加载更多数据的逻辑即可，加载完成后调用
     * addMoreData 将数据加入列表尾部
     */
    public void loadMoreData() {
        if (mSmartRefreshLayout.autoLoadMore()) {
//            LogUtils.d("loadMoreData ok");
        } else {
//            LogUtils.d("loadMoreData fail");
            if (iRequestAction != null) {
                iRequestAction.requestMoreData();
            }
        }

    }


    /**
     * 在请求后正常返回，但没有数据的时候显示，一般不用主动调用
     * 在调用 setNewData() 方法时会判断数据是否空，如果空会调用 showEmptyView() 显示空状态视图
     * 此方法会调用复位刷新控件状态 SmartRefreshLayout.finishRefresh()
     */
    public void showEmptyView() {
        mSmartRefreshLayout.finishRefresh();
        if (mEmptyView == null) {
            return;
        }
        mSmartRefreshLayout.setVisibility(GONE);
        if (mErrorView != null)
            mErrorView.setVisibility(GONE);
        mEmptyView.setVisibility(VISIBLE);
    }

    /**
     * 加载失败，如网络连接失败，需要主动调用显示
     * 因为错误状态各种各样，例如无网络连接，服务器宕机，手机信号不好等情况，都会导致获取数据失败
     * 所以需要根据具体情况判断显示时机
     * 此方法会调用复位刷新控件状态 SmartRefreshLayout.finishRefresh()
     */
    public void showErrorView() {
        mSmartRefreshLayout.finishRefresh();
        if (mErrorView == null) {
            return;
        }
        mSmartRefreshLayout.setVisibility(GONE);
        mErrorView.setVisibility(VISIBLE);
        if (mEmptyView != null)
            mEmptyView.setVisibility(GONE);
    }

    /**
     * 隐藏无数据默认视图
     */
    public void hideEmptyView() {
        mSmartRefreshLayout.setVisibility(VISIBLE);
        if (mEmptyView != null) {
            mEmptyView.setVisibility(GONE);
        }
    }

    /**
     * 隐藏错误提示视图
     */
    public void hideErrorView() {
        mSmartRefreshLayout.setVisibility(VISIBLE);
        if (mErrorView != null) {
            mErrorView.setVisibility(GONE);
        }
    }

    public RecyclerView getRecyclerView() {
        return mRecyclerView;
    }

    public BaseQuickAdapter getAdapter() {
        return mAdapter;
    }

    /**
     * 添加数据到列表尾部
     * 此方法会调用复位刷新控件状态 SmartRefreshLayout.finishLoadMore()
     *
     * @param newData
     */
    public void addMoreData(List<?> newData) {

        finishLoadMore();

        if (newData.isEmpty()) {
            return;
        }

        if (mAdapter != null) {
            hideEmptyView();
            mAdapter.addData(newData);
        }

        if (newData.size() > 0 && typePositionMap.size() == 0) {
            for (int i = 0, size = newData.size(); i < size; i++) {
                if (!typePositionMap.containsKey(mAdapter.getItemViewType(i))) {
                    typePositionMap.put(mAdapter.getItemViewType(i), i);
                }
            }
        }
    }

    /**
     * 清空全部数据，设置最新数据
     * 此方法会调用复位刷新控件状态 SmartRefreshLayout.finishRefresh()
     *
     * @param newData
     */
    public void setNewData(List<?> newData) {
        hideErrorView();
        hideEmptyView();

        finishRefresh();

        if (mAdapter == null) {
            return;
        }

        if (newData == null || newData.isEmpty()) {
            mAdapter.getData().clear();
            showEmptyView();
            return;
        }

        hideEmptyView();
        mAdapter.setNewInstance(newData);

        initTypePositionMap();

    }

    private void initTypePositionMap() {
        typePositionMap.clear();
        if (mAdapter.getData().size() > 0 && typePositionMap.size() == 0) {
            for (int i = 0, size = mAdapter.getData().size(); i < size; i++) {
                if (!typePositionMap.containsKey(mAdapter.getItemViewType(i))) {
                    typePositionMap.put(mAdapter.getItemViewType(i), i);
                }
            }
        }
    }

    /**
     * @param baseQuickAdapter
     * @return
     */
    public RefreshRecyclerView setAdapter(BaseQuickAdapter baseQuickAdapter) {
        mAdapter = baseQuickAdapter;
        mAdapter.setOnItemClickListener((adapter, view, position) -> {
            if (OnItemClickListener != null) {
                if (checkClickValid(view.getId())) {
                    OnItemClickListener.onItemClick(adapter.getItem(position), position);
                }
            }
        });
        mAdapter.setOnItemChildClickListener((adapter, view, position) -> {
            if (OnItemClickListener != null) {
                if (checkClickValid(view.getId())) {
                    OnItemClickListener.onChildClick(view.getId(), adapter.getItem(position), position);
                }
            }
        });

        initTypePositionMap();

        mRecyclerView.setAdapter(mAdapter);

        return this;
    }

    /**
     * 列表添加头部视图
     *
     * @param view
     * @return
     */
    public RefreshRecyclerView addAdapterHeader(View view) {
        if (view == null) {
            return this;
        }
        if (mAdapter != null && !mAdapterHeaderList.contains(view)) {
            mAdapter.addHeaderView(view);
            mAdapterHeaderList.add(view);
        }
        return this;
    }

    /**
     * 列表移除头部视图
     *
     * @param view
     * @return
     */
    public RefreshRecyclerView removeAdapterHeader(View view) {
        if (view == null) {
            return this;
        }
        if (mAdapter != null && mAdapterHeaderList.contains(view)) {
            mAdapter.removeHeaderView(view);
            mAdapterHeaderList.remove(view);
        }
        return this;
    }

    /**
     * 列表添加尾部视图
     *
     * @param view
     * @return
     */
    public RefreshRecyclerView addAdapterFooter(View view) {
        if (view == null) {
            return this;
        }
        if (mAdapter != null && !mAdapterFooterList.contains(view)) {
            mAdapter.addFooterView(view);
            mAdapterFooterList.add(view);
        }
        return this;
    }

    /**
     * 列表移除尾部视图
     *
     * @param view
     * @return
     */
    public RefreshRecyclerView removeAdapterFooter(View view) {
        if (view == null) {
            return this;
        }
        if (mAdapter != null && mAdapterFooterList.contains(view)) {
            mAdapter.removeFooterView(view);
            mAdapterFooterList.remove(view);
        }
        return this;
    }

    /**
     * 设置列表无数据时显示的 View
     *
     * @param view
     * @return
     */
    public RefreshRecyclerView setEmptyView(View view) {
        if (mEmptyView != null) {
            removeView(mEmptyView);
            mEmptyView = null;
        }
        mEmptyView = view;
        if (mEmptyView != null) {
            this.addView(mEmptyView);
            mEmptyView.setVisibility(GONE);
            mEmptyView.setOnClickListener(this);
        }
        return this;
    }

    /**
     * 设置错误提示的 View，例如数据加载失败时显示的 View
     *
     * @param errorView
     * @return
     */
    public RefreshRecyclerView setErrorView(View errorView) {
        if (mErrorView != null) {
            removeView(mErrorView);
            mErrorView = null;
        }
        mErrorView = errorView;
        if (mErrorView != null) {
            this.addView(mErrorView);
            mErrorView.setVisibility(GONE);
            mErrorView.setOnClickListener(this);
        }
        return this;
    }

    /**
     * 滚动到指定类型的位置
     *
     * @param itemType
     */
    public void scrollToPositionByType(int itemType) {
        if (typePositionMap != null && typePositionMap.containsKey(itemType)) {
            mRecyclerView.smoothScrollToPosition(typePositionMap.get(itemType));
        }
    }

    /**
     * 根据类型滚动到指定位置后再发生一个偏移量
     *
     * @param itemType
     * @param offset
     */
    public void scrollToPositionByTypeWithOffset(int itemType, int offset) {
        if (typePositionMap != null && typePositionMap.containsKey(itemType)) {
            LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
            layoutManager.scrollToPositionWithOffset(typePositionMap.get(itemType), offset);
        }
    }

    /**
     * 滚动到指定的位置
     *
     * @param position
     */
    public void scrollToPosition(int position) {
        mRecyclerView.smoothScrollToPosition(position);
    }

    /**
     * 滚动到指定位置后再发生一个偏移量
     *
     * @param position
     * @param offset
     */
    public void scrollToPositionWithOffset(int position, int offset) {
        LinearLayoutManager layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager();
        layoutManager.scrollToPositionWithOffset(position, offset);
    }

    /**
     * 根据itemType找Position
     */
    public int getPositionByItemType(int itemType) {
        if (typePositionMap != null && typePositionMap.containsKey(itemType)) {
            return typePositionMap.get(itemType);
        } else {
            return 0;
        }
    }

    /**
     * 根据Position和Id找对应的View
     *
     * @param position
     * @param id
     * @return
     */
    public View findViewInAdapter(@NonNull int position, @IdRes int id) {
        return mAdapter.getViewByPosition(position, id);
    }

    /**
     * 完成刷新动作，复位下拉刷新控件
     */
    public void finishRefresh() {
        mSmartRefreshLayout.finishRefresh();
    }

    /**
     * 完成加载更多动作，复位上拉加载控件
     */
    public void finishLoadMore() {
        mSmartRefreshLayout.finishLoadMore();
    }

    /**
     * 检查当前ID是否在点击有效时间内
     *
     * @return
     */
    protected boolean checkClickValid(int viewId) {
        boolean isValid;
        firClickTime = clickTimeMap.get(viewId) == null ? firClickTime : clickTimeMap.get(viewId);
        if (System.currentTimeMillis() - firClickTime > CLICK_INTERVAL) {
            firClickTime = System.currentTimeMillis();
            isValid = true;
        } else {
            firClickTime = System.currentTimeMillis();
            isValid = false;
        }
        clickTimeMap.put(viewId, firClickTime);
        return isValid;
    }

    /**
     * 列表item点击事件
     *
     * @param OnItemClickListener
     */
    public void setOnItemClickListener(RefreshRecyclerView.OnItemClickListener<?> OnItemClickListener) {
        this.OnItemClickListener = OnItemClickListener;
    }

    /**
     * EmptyView 和 ErrorView 的点击事件
     *
     * @param OnStateViewClickListener
     */
    public void setOnStateClickListener(OnStateViewClickListener OnStateViewClickListener) {
        this.OnStateClickListener = OnStateViewClickListener;
    }

    public SmartRefreshLayoutCompat getSmartRefreshLayout() {
        return mSmartRefreshLayout;
    }

    /**
     * 请求数据的动作，2种回调情况
     * 1.请求新数据
     * 2.请求更多数据
     */
    public interface IRequestAction {

        /**
         * 请求新数据时回调
         */
        void requestNewData();

        /**
         * 加载更多数据时回调
         */
        void requestMoreData();
    }

    /**
     * Item点击回调
     *
     * @param <T>
     */
    public interface OnItemClickListener<T> {
        /**
         * RecyclerView点击事件
         *
         * @param data
         * @param position
         */
        void onItemClick(@NotNull T data, int position);

        /**
         * Adapter 子Item点击事件
         *
         * @param id
         * @param data
         * @param position
         */
        void onChildClick(int id, @NotNull T data, int position);
    }

    /**
     * EmptyView的点击事件，或者ErrorView的点击事件
     */
    public interface OnStateViewClickListener {

        void onEmptyViewClick(View emptyView);

        void onErrorViewClick(View errorView);
    }

}
